#include "gtkbuttonprivate.h"
#include "gtkactionhelperprivate.h"
+#include "gtkbuildable.h"
#include "gtkcheckbutton.h"
#include "gtkgestureclick.h"
#include "gtkeventcontrollerkey.h"
+#include "gtkbinlayout.h"
#include "gtkimage.h"
#include "gtkintl.h"
#include "gtklabel.h"
struct _GtkButtonPrivate
{
+ GtkWidget *child;
+
GtkActionHelper *action_helper;
GtkGesture *gesture;
gboolean was_grabbed);
static void gtk_button_do_release (GtkButton *button,
gboolean emit_clicked);
+static void gtk_button_set_child_type (GtkButton *button, guint child_type);
+static void gtk_button_buildable_iface_init (GtkBuildableIface *iface);
static void gtk_button_actionable_iface_init (GtkActionableInterface *iface);
-static void gtk_button_set_child_type (GtkButton *button, guint child_type);
-
static GParamSpec *props[LAST_PROP] = { NULL, };
static guint button_signals[LAST_SIGNAL] = { 0 };
-G_DEFINE_TYPE_WITH_CODE (GtkButton, gtk_button, GTK_TYPE_BIN,
+G_DEFINE_TYPE_WITH_CODE (GtkButton, gtk_button, GTK_TYPE_WIDGET,
G_ADD_PRIVATE (GtkButton)
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, gtk_button_buildable_iface_init)
G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIONABLE, gtk_button_actionable_iface_init))
static void
-gtk_button_add (GtkContainer *container, GtkWidget *child)
+gtk_button_unmap (GtkWidget *widget)
{
- GtkButton *button = GTK_BUTTON (container);
- GtkButtonPrivate *priv = gtk_button_get_instance_private (button);
-
- if (priv->child_type != WIDGET_CHILD)
- gtk_container_remove (container, gtk_bin_get_child (GTK_BIN (button)));
+ GtkButtonPrivate *priv = gtk_button_get_instance_private (GTK_BUTTON (widget));
- gtk_button_set_child_type (button, WIDGET_CHILD);
+ priv->in_button = FALSE;
- GTK_CONTAINER_CLASS (gtk_button_parent_class)->add (container, child);
+ GTK_WIDGET_CLASS (gtk_button_parent_class)->unmap (widget);
}
static void
-gtk_button_remove (GtkContainer *container, GtkWidget *child)
+gtk_button_compute_expand (GtkWidget *widget,
+ gboolean *hexpand,
+ gboolean *vexpand)
{
- GtkButton *button = GTK_BUTTON (container);
-
- gtk_button_set_child_type (button, WIDGET_CHILD);
+ GtkButtonPrivate *priv = gtk_button_get_instance_private (GTK_BUTTON (widget));
- GTK_CONTAINER_CLASS (gtk_button_parent_class)->remove (container, child);
+ if (priv->child)
+ {
+ *hexpand = gtk_widget_compute_expand (priv->child, GTK_ORIENTATION_HORIZONTAL);
+ *vexpand = gtk_widget_compute_expand (priv->child, GTK_ORIENTATION_VERTICAL);
+ }
+ else
+ {
+ *hexpand = FALSE;
+ *vexpand = FALSE;
+ }
}
-static void
-gtk_button_unmap (GtkWidget *widget)
+static GtkSizeRequestMode
+gtk_button_get_request_mode (GtkWidget *widget)
{
GtkButtonPrivate *priv = gtk_button_get_instance_private (GTK_BUTTON (widget));
- priv->in_button = FALSE;
-
- GTK_WIDGET_CLASS (gtk_button_parent_class)->unmap (widget);
+ if (priv->child)
+ return gtk_widget_get_request_mode (priv->child);
+ else
+ return GTK_SIZE_REQUEST_CONSTANT_SIZE;
}
static void
{
GObjectClass *gobject_class;
GtkWidgetClass *widget_class;
- GtkContainerClass *container_class;
gobject_class = G_OBJECT_CLASS (klass);
widget_class = (GtkWidgetClass*) klass;
- container_class = GTK_CONTAINER_CLASS (klass);
gobject_class->dispose = gtk_button_dispose;
gobject_class->set_property = gtk_button_set_property;
widget_class->unmap = gtk_button_unmap;
widget_class->grab_focus = gtk_widget_grab_focus_self;
widget_class->focus = gtk_widget_focus_self;
-
- container_class->add = gtk_button_add;
- container_class->remove = gtk_button_remove;
+ widget_class->compute_expand = gtk_button_compute_expand;
+ widget_class->get_request_mode = gtk_button_get_request_mode;
klass->clicked = NULL;
klass->activate = gtk_real_button_activate;
G_TYPE_NONE, 0);
widget_class->activate_signal = button_signals[ACTIVATE];
+ gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_BUTTON_ACCESSIBLE);
gtk_widget_class_set_css_name (widget_class, I_("button"));
}
GtkButton *button = GTK_BUTTON (object);
GtkButtonPrivate *priv = gtk_button_get_instance_private (button);
+ g_clear_pointer (&priv->child, gtk_widget_unparent);
g_clear_object (&priv->action_helper);
G_OBJECT_CLASS (gtk_button_parent_class)->dispose (object);
g_value_set_string (value, gtk_button_get_icon_name (button));
break;
case PROP_CHILD:
- g_value_set_object (value, gtk_button_get_child (button));
+ g_value_set_object (value, priv->child);
break;
case PROP_ACTION_NAME:
g_value_set_string (value, gtk_action_helper_get_action_name (priv->action_helper));
iface->set_action_target_value = gtk_button_set_action_target_value;
}
+static GtkBuildableIface *parent_buildable_iface;
+
+static void
+gtk_button_buildable_add_child (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const gchar *type)
+{
+ if (GTK_IS_WIDGET (child))
+ gtk_button_set_child (GTK_BUTTON (buildable), GTK_WIDGET (child));
+ else
+ parent_buildable_iface->add_child (buildable, builder, child, type);
+}
+
+static void
+gtk_button_buildable_iface_init (GtkBuildableIface *iface)
+{
+ parent_buildable_iface = g_type_interface_peek_parent (iface);
+
+ iface->add_child = gtk_button_buildable_add_child;
+}
+
/**
* gtk_button_new:
*
g_return_if_fail (GTK_IS_BUTTON (button));
- child = gtk_bin_get_child (GTK_BIN (button));
-
- if (priv->child_type != LABEL_CHILD || child == NULL)
+ if (priv->child_type != LABEL_CHILD || priv->child == NULL)
{
- if (child != NULL)
- gtk_button_remove (GTK_CONTAINER (button), child);
-
child = gtk_label_new (NULL);
if (priv->use_underline)
{
gtk_label_set_mnemonic_widget (GTK_LABEL (child), GTK_WIDGET (button));
}
if (GTK_IS_CHECK_BUTTON (button))
- {
- gtk_label_set_xalign (GTK_LABEL (child), 0.0);
- }
- gtk_button_add (GTK_CONTAINER (button), child);
+ gtk_label_set_xalign (GTK_LABEL (child), 0.0);
+
+ gtk_button_set_child (button, child);
gtk_widget_remove_css_class (GTK_WIDGET (button), "image-button");
gtk_widget_add_css_class (GTK_WIDGET (button), "text-button");
}
- gtk_label_set_label (GTK_LABEL (child), label);
+ gtk_label_set_label (GTK_LABEL (priv->child), label);
gtk_button_set_child_type (button, LABEL_CHILD);
g_object_notify_by_pspec (G_OBJECT (button), props[PROP_LABEL]);
}
g_return_val_if_fail (GTK_IS_BUTTON (button), NULL);
if (priv->child_type == LABEL_CHILD)
- {
- GtkWidget *child = gtk_bin_get_child (GTK_BIN (button));
- return gtk_label_get_label (GTK_LABEL (child));
- }
+ return gtk_label_get_label (GTK_LABEL (priv->child));
return NULL;
}
*/
void
gtk_button_set_use_underline (GtkButton *button,
- gboolean use_underline)
+ gboolean use_underline)
{
GtkButtonPrivate *priv = gtk_button_get_instance_private (button);
{
if (priv->child_type == LABEL_CHILD)
{
- GtkWidget *child;
- child = gtk_bin_get_child (GTK_BIN (button));
-
- gtk_label_set_use_underline (GTK_LABEL (child), use_underline);
- gtk_label_set_mnemonic_widget (GTK_LABEL (child), GTK_WIDGET (button));
+ gtk_label_set_use_underline (GTK_LABEL (priv->child), use_underline);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (priv->child), GTK_WIDGET (button));
}
priv->use_underline = use_underline;
const char *icon_name)
{
GtkButtonPrivate *priv = gtk_button_get_instance_private (button);
- GtkWidget *child;
g_return_if_fail (GTK_IS_BUTTON (button));
g_return_if_fail (icon_name != NULL);
- child = gtk_bin_get_child (GTK_BIN (button));
-
- if (priv->child_type != ICON_CHILD || child == NULL)
+ if (priv->child_type != ICON_CHILD || priv->child == NULL)
{
- child = gtk_image_new_from_icon_name (icon_name);
+ GtkWidget *child = gtk_image_new_from_icon_name (icon_name);
gtk_button_set_child (GTK_BUTTON (button), child);
gtk_widget_remove_css_class (GTK_WIDGET (button), "text-button");
gtk_widget_add_css_class (GTK_WIDGET (button), "image-button");
}
else
{
- gtk_image_set_from_icon_name (GTK_IMAGE (child), icon_name);
+ gtk_image_set_from_icon_name (GTK_IMAGE (priv->child), icon_name);
}
gtk_button_set_child_type (button, ICON_CHILD);
g_return_val_if_fail (GTK_IS_BUTTON (button), NULL);
if (priv->child_type == ICON_CHILD)
- {
- GtkWidget *child = gtk_bin_get_child (GTK_BIN (button));
-
- return gtk_image_get_icon_name (GTK_IMAGE (child));
- }
+ return gtk_image_get_icon_name (GTK_IMAGE (priv->child));
return NULL;
}
gtk_button_set_child (GtkButton *button,
GtkWidget *child)
{
+ GtkButtonPrivate *priv = gtk_button_get_instance_private (button);
+
g_return_if_fail (GTK_IS_BUTTON (button));
g_return_if_fail (child == NULL || GTK_IS_WIDGET (child));
- if (gtk_bin_get_child (GTK_BIN (button)))
- gtk_button_remove (GTK_CONTAINER (button),
- gtk_bin_get_child (GTK_BIN (button)));
- gtk_button_add (GTK_CONTAINER (button), child);
+ g_clear_pointer (&priv->child, gtk_widget_unparent);
+
+ priv->child = child;
+
+ if (priv->child)
+ gtk_widget_set_parent (priv->child, GTK_WIDGET (button));
+
+ gtk_button_set_child_type (button, WIDGET_CHILD);
g_object_notify (G_OBJECT (button), "child");
}
GtkWidget *
gtk_button_get_child (GtkButton *button)
{
+ GtkButtonPrivate *priv = gtk_button_get_instance_private (button);
+
g_return_val_if_fail (GTK_IS_BUTTON (button), NULL);
- return gtk_bin_get_child (GTK_BIN (button));
+ return priv->child;
}